﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using LuaInterface;

namespace Gigamud.LuaEngine
{
    public class LuaEventArgs : EventArgs
    {
        private string _eventName;
        private Dictionary<string, string> _eventArgs;

        public LuaEventArgs(string EventName, Dictionary<string, string> Args)
        {
            _eventName = EventName;
            _eventArgs = Args;
        }

        public string EventName
        {
            get { return _eventName; }
            set { _eventName = value; }
        }

        public Dictionary<string, string> Args
        {
            get { return _eventArgs; }
            set { _eventArgs = value; }
        }
    }
    
    internal class LuaEngine : LuaGlobalFunctions
    {
        public event EventHandler<LuaEventArgs> LuaEvent;

        public LuaEngine(ConnectionController Connection) : base(Connection)
        {
        }

        ~LuaEngine()
        {
            _connection.OnDisconnect -= connection_OnDisconnect;
            _connection.NewChar -= connection_NewChar;
            this.Dispose();
        }

        public void Initialize()
        {
            _connection.OnDisconnect += new EventHandler<WalburySoftware.TerminalControl.TerminalEventArgs>(connection_OnDisconnect);
            _connection.NewChar += new EventHandler<WalburySoftware.TerminalControl.TerminalEventArgs>(connection_NewChar);
            DoFile(_scriptLocation + "Constants.lua");
            DoFile(_scriptLocation + "proof_of_concept.lua");
        }

        private void RaiseEvent() {}

        private void connection_OnDisconnect(object sender, WalburySoftware.TerminalControl.TerminalEventArgs args)
        {
            string msg = new string(args.MessageOne);
            if (_registeredFunctions.ContainsKey("EVENT_DISCONNECT"))
            {
                string function = _registeredFunctions["EVENT_DISCONNECT"];
                this.GetFunction(function).Call(msg);
                MessageBox.Show(msg);
            }
        }

        private void connection_NewChar(object sender, WalburySoftware.TerminalControl.TerminalEventArgs args)
        {
            string ch = new string(args.MessageOne);
            if (_registeredFunctions.ContainsKey("EVENT_NEW_CHAR"))
            {
                string function = _registeredFunctions["EVENT_NEW_CHAR"];
                try
                {
                    this.GetFunction(function).Call(ch);
                }
                catch (LuaScriptException e)
                {
                    MessageBox.Show(e.Message);
                }
                //MessageBox.Show(ch);
            }
        }
    }

    internal abstract class LuaGlobalFunctions : Lua
    {
        protected Dictionary<string, string> _registeredFunctions;
        protected List<string> _events;
        protected ConnectionController _connection;
        protected string _scriptLocation;
        
        public LuaGlobalFunctions(ConnectionController Connection)
        {
            _connection = Connection;
            RegisterGlobals();

            _events = new List<string>();
            EnumerateEvents();

            _registeredFunctions = new Dictionary<string, string>();

            _scriptLocation = "C:\\Users\\John\\Documents\\Visual Studio 2010\\Projects\\Gigamud\\lib\\scripts\\";

        }

        ~LuaGlobalFunctions()
        {
        }

        internal void Reload()
        {
            _registeredFunctions.Clear();
            List<string> globals = new List<string>();
            foreach (object global in this.Globals)
            {
                globals.Add(global.ToString());
            }
            foreach (string global in globals)
            {
                this[global] = null;
            }
            RegisterGlobals();
            try
            {
                DoFile(_scriptLocation + "Constants.lua");
                DoFile(_scriptLocation + "proof_of_concept.lua");
            }
            catch (LuaScriptException e)
            {
                MessageBox.Show(e.Message);
            }
            
        }

        private void RegisterGlobals()
        {
            RegisterFunction("RegisterForEvent", this, this.GetType().GetMethod("RegisterForEvent"));
            RegisterFunction("GetValidEvents", this, this.GetType().GetMethod("GetValidEvents"));
            RegisterFunction("SendText", this, this.GetType().GetMethod("SendText"));
            RegisterFunction("Disconnect", this, this.GetType().GetMethod("Disconnect"));
        }

        private void EnumerateEvents()
        {
            _events.Add("EVENT_NEW_CHAR");
            _events.Add("EVENT_DISCONNECT");
        }

        public void RegisterForEvent(string EventName, string Function)
        {
            //MessageBox.Show(String.Format("Registering for event {0} as {1}.", EventName, Function));

            int idx = _events.FindIndex(
            delegate(string find)
            {
                return find == EventName;
            }
            );
            //MessageBox.Show(Convert.ToString(idx));
            //MessageBox.Show(EventName);
            if (idx > -1)
            {
                if (!_registeredFunctions.ContainsKey(EventName))
                {
                    _registeredFunctions.Add(EventName, Function);
                }
            }
        }

        public LuaTable GetValidEvents()
        {
            this.NewTable("events");
            LuaTable events = this.GetTable("events");
            foreach (string _event in _events)
            {
                events[_event] = _event;
            }
            return events;
        }

        public void SendText(string TextToSend)
        {
            _connection.SendText(TextToSend);
        }

        public void Disconnect(string message)
        {
            _connection.Disconnect(message);
        }
    }
}
